package logger

import (
	"fmt"
	"os"
	"path"
	"sync"
	"sync/atomic"
	"unsafe"

	"src/zeus/common"
	"src/zeus/threads"

	"github.com/cxzgb123/toml"
)

/*
服务器上的日志系统
如果是Test运行用到日志的话,使用的是默认配置不会生成文件等逻辑
如果是正常的服务,需要在使用之前运行Init逻辑
*/

var (
	logGlobal *LoggerMgr
	one       sync.Once
)

// func init() {
// 	servername := flags.GetFlagByString(common.ServerName)

// 	Init(path.Join(common.GetResPath(), "config", "logn.toml"), servername, threads.NewThreadGo())

// }
type IScreen interface {
	GetScreenPar() []interface{}
}

// 初始化日志系统
func Init(cfg string, srvname string, thgo *threads.ThreadGo) {
	one.Do(func() {
		var logcfg *LogFileConfig
		if _, err := os.Stat(cfg); !os.IsNotExist(err) {
			logcfg = new(LogFileConfig)
			_, err := toml.DecodeFile(cfg, logcfg)
			if err != nil {
				fmt.Printf("Logger Init log.toml err:%s\n", err)
			}
		} else {
			fmt.Println("Logger Init log.toml not exist.")
			logcfg = defaultLogConfig
			//如果没有对应的日志配置就生成一个
			GenLogConfigFile(cfg)
		}
		logcfg.LogFileName = srvname
		logcfg.LogFilePath = path.Join(common.GetResPath(), logcfg.LogFilePath)
		logGlobal = newLoggerMgr(thgo,
			LoggerSetConfig(logcfg))
		// fmt.Printf("%+v\n", logcfg)
	})
}

func Flush() {
	logGlobal.Stop()
}

// 重新加载日志Key
func ReLoadKeys(Keys []string) {
	logGlobal.lk.Lock()
	defer logGlobal.lk.Unlock()
	logGlobal.tmpKeyList = Keys
}

// 重新加载日志等级
func ReLoadLevel(level logLevel) {
	//logGlobal.lk.Lock()
	//defer logGlobal.lk.Unlock()
	atomic.StoreInt64((*int64)(unsafe.Pointer(&logGlobal.config.LogFileLevel)), int64(level))
}

func CheckKey(logKey LogKeyEnum) bool {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	return logGlobal.checkKey(logKey)
}

func CheckGMKey(logKey LogKeyEnum, all []interface{}) bool {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	return logGlobal.checkGmKey(logKey, all)
}

// gm增加指定 key日志
func GmAddKey(key LogKeyEnum, OID []uint64) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	logGlobal.gmAddKey(key, OID)
}

// 调试等级上线后不需要看到的日志,调试用,可以使用Key来临时开关的日志
func Debugf(logKey LogKeyEnum, format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelDebug {
		return
	}
	if !logGlobal.checkKey(logKey) {
		return
	}
	logGlobal.debug(logKey, fmt.Sprintf(format, params...))
}

// 信息等级上线后正常需要看到的日志,报告状态等
func Infof(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelInfo {
		return
	}
	logGlobal.info(fmt.Sprintf(format, params...))
}

// 警告等级一般是配置表有错,但不影响正常运行等
func Warnf(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelWarn {
		return
	}
	logGlobal.warn(fmt.Sprintf(format, params...))
	// _, file, line, _ := runtime.Caller(1)
	// logGlobal.warn(fmt.Sprint(format, "\n", file, ":", line), params...)
}

// 错误等级(输出错误日志)一般是已知错误,发生了需要处理
func Errorf(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelError {
		return
	}
	logGlobal.error(fmt.Sprintf(format, params...))
}

// 致命等级(输出致命日志)一般是未知错误,发生了里发报警
func Fatalf(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelFatal {
		return
	}
	logGlobal.fatal(fmt.Sprintf(format, params...))
}

// 调试等级上线后不需要看到的日志,调试用,可以使用Key来临时开关的日志
func Debug(logKey LogKeyEnum, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelDebug {
		return
	}
	if !logGlobal.checkKey(logKey) {
		return
	}
	logGlobal.debug(logKey, fmt.Sprintf(getFormat(len(params)), params...))
}

// 调试等级上线后不需要看到的日志,调试用,可以使用Key来临时开关的日志(这个会受GM 进行筛选)
func ScreenDebug(logKey LogKeyEnum, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelDebug {
		return
	}
	logGlobal.debug(logKey, fmt.Sprintf(getFormat(len(params)), params...))
}

// 信息等级上线后正常需要看到的日志,报告状态等
func Info(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelInfo {
		return
	}
	logGlobal.info(fmt.Sprintf(getFormat(len(params)), params...))
}

// 警告等级一般是配置表有错,但不影响正常运行等
func Warn(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelWarn {
		return
	}
	logGlobal.warn(fmt.Sprintf(getFormat(len(params)), params...))
	// _, file, line, _ := runtime.Caller(1)
	// logGlobal.warn(fmt.Sprint(getFormat(len(params)), "\n", file, ":", line), params...)

}

// 警告等级一般是配置表有错,但不影响正常运行等
func MysqlWarn(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelWarn {
		return
	}
	logGlobal.warn(fmt.Sprintf(getFormat(len(params)), params...))
}

// 错误等级(输出错误日志)一般是已知错误,发生了需要处理
func Error(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelError {
		return
	}
	logGlobal.error(fmt.Sprintf(getFormat(len(params)), params...))
}

// 致命等级(输出致命日志)一般是未知错误,发生了里发报警
func Fatal(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelFatal {
		return
	}
	logGlobal.fatal(fmt.Sprintf(getFormat(len(params)), params...))
}

const (
	LOGFILE_INIT_NUMBER int = 0
)
